package com.jz.netthings.system.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.jz.netthings.bean.system.JyMenu;
import com.jz.netthings.bean.system.JyUser;
import com.jz.netthings.exception.AdscmSystemException;
import com.jz.netthings.security.utils.Token;
import com.jz.netthings.support.SecurityConstants;
import com.jz.netthings.system.mapper.mysql.JyMenuMapper;
import com.jz.netthings.system.service.JyMenuService;
import com.jz.netthings.utils.AdscmBaseUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <p>
 * 系统菜单表 服务实现类
 * </p>
 *
 * @author yyy
 * @since 2018-08-01
 */
@Service
public class JyMenuServiceImpl extends ServiceImpl<JyMenuMapper, JyMenu> implements JyMenuService{

    Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    RedisTemplate<Object,Token> tokenRedisTemplate;
    @Autowired
    JyMenuMapper jyMenuMapper;

    @Transactional
    @Override
    public void delMenu(int menuId) throws  AdscmSystemException {
        logger.info("删除菜单【"+menuId+"】...");
        JyMenu menu = jyMenuMapper.selectById(menuId);
        if (menu != null){
            //看是否有子菜单，如果有，则不能删除
            EntityWrapper<JyMenu> wapper = new EntityWrapper();
            wapper.where("parentId = " + menu.getId());
            Integer count = jyMenuMapper.selectCount(wapper);//.selectList(wapper);
            if (count != null && count>0){
                throw new AdscmSystemException("待删除的菜单【"+menu.getName()+"】有关联的子菜单，不能删除");
            }else {
                jyMenuMapper.deleteById(menuId);
                //修改内存中的menu
                this.updateSecurityConstantsMenus(3,menu);
            }
        }else {
            throw new AdscmSystemException("待删除的菜单ID【"+menuId+"】没有对应的菜单，删除失败");
        }


    }

//    @Override
//    public List<JyMenu> getUsersUrls(String tokenId) throws AdscmSystemException {
//
//        logger.info("获取指定用户能访问的所有菜单集合...");
//
//        List<JyMenu> menuList = null;
//        if (AdscmBaseUtils.getInstance().isNotEmpty(tokenId,null)){
//            Token token = AdscmBaseUtils.getInstance().getTokenByTokenId(tokenId, tokenRedisTemplate);
//            if (AdscmBaseUtils.getInstance().isNotEmpty(token,"user")){
//                JyUser user = token.getUser();
//
//                List<JyMenu> menus = user.getMenus();
//                if (menus != null && menus.size()>0){
//                    for (JyMenu menu :
//                            menus) {
//
//                        //将 menu 的 show 标志置为true
//                        menu.setMenuShow(true);
//
//                        if (menuList == null){
//                            menuList = new ArrayList<>();
//                        }
//                        //这里先把顶级菜单全部获取出来
//                        if (menu.getParentId() != null && menu.getParentId().intValue() == 1){
//                            menuList.add(menu);
//                        }
//                    }
//
//                    //递归获取子菜单
//                    if (menuList != null && menuList.size()>0){
//                        for (JyMenu menu:
//                                menuList) {
//                            recursionJyMenu(menu,menus);
//                        }
//                    }
//                }
//
//
//
//            }else {
//                throw new AdscmSystemException("未登录，不能获取登录浆员的访问菜单集合...");
//            }
//        }else {
//            throw new AdscmSystemException("tokenId 为 null，不能获取登录浆员的访问菜单集合...");
//        }
//        return menuList;
//    }

    @Transactional
    @Override
    public void addMenu(JyMenu menu) throws AdscmSystemException {

        if (AdscmBaseUtils.getInstance().isNotEmpty(menu,"name")){
            logger.info("增加菜单【"+menu.getName()+"】...");

           /* menu.setKeepAlive(1);
            menu.setRequireAuth("1");
            menu.setEnabled(1);

            if (menu.getSrcType() == null){
                throw new AdscmSystemException("参数异常：请选择资源类型！");
            }
            if (menu.getParentId() == null){
                throw new AdscmSystemException("参数异常：请选择父级菜单！");
            }
            JyMenu parentMenu = jyMenuMapper.selectById(menu.getParentId());

            if (parentMenu != null && parentMenu.getSrcType().intValue() == 2){
                throw new AdscmSystemException("资源下面不能添加子集菜单或资源！");
            }
            //看当前菜单下面有无其他类型的子菜单
            boolean flag = true;
            Wrapper<JyMenu> wrapper = new EntityWrapper<>();
            wrapper.eq("parentId",menu.getParentId());
            List<JyMenu> menus = jyMenuMapper.selectList(wrapper);
            if (menus != null && menus.size()>0){
                for (JyMenu jyMenu : menus) {
                    int srcType = jyMenu.getSrcType();
                    if (srcType != menu.getSrcType().intValue()){
                        flag = false;
                        break;
                    }
                }
            }*/

            boolean flag = validateMenu(menu);

            if (flag){
                jyMenuMapper.insert(menu);
            }else{
                throw new AdscmSystemException("当前菜单所属的父级菜单下面只能存在一种资源类型！");
            }


            //修改内存中的menu
            this.updateSecurityConstantsMenus(1,menu);


        }else {
            throw new AdscmSystemException("菜单参数异常【"+menu+"】");
        }

    }

    /**
     * 修改内存中的menu
     * @param type : 类型： 1:增加，2:修改，3:删除
     */
    private void updateSecurityConstantsMenus(int type,JyMenu menu){


        if (menu != null && menu.getId() != null){

            if (menu.getSrcType().intValue() != 1){
                return;
            }
            if (type == 1 && menu.getParentId() == 0){
                SecurityConstants.ALL_MENUS.add(menu);
            }else {

                for(int i=0;i<SecurityConstants.ALL_MENUS.size();i++){
                    JyMenu jyMenu = SecurityConstants.ALL_MENUS.get(i);

                    if(menu.getParentId() == 0){
                        if (menu.getId().intValue() == jyMenu.getId().intValue()){
                            if (type == 2){
                                SecurityConstants.ALL_MENUS.set(i,menu);
                            }else if(type == 3){
                                SecurityConstants.ALL_MENUS.remove(jyMenu);
                                return;
                            }
                        }
                    }else{
                        List<JyMenu> children = jyMenu.getChildren();
                        if (menu.getParentId().intValue() == jyMenu.getId().intValue()){
                            if (children == null) {
                                children = new ArrayList<>();
                                jyMenu.setChildren(children);
                            }
                            operatorChildren(type,children,menu);
                            return;
                        }else {
                            //看所有子集是否存在匹配得上的
                            boolean flag = updateSecurityConstantsMenusChildren(type,children,menu);
                            if (flag){
                                break;
                            }
                        }

                    }

                }


                /*for (JyMenu menus : SecurityConstants.ALL_MENUS) {

                    if(menu.getParentId() == 0){
                        if (menu.getId().intValue() == menus.getId().intValue()){
                            if (type == 2){

                            }else if(type == 3){
                                SecurityConstants.ALL_MENUS.remove(menus);
                                return;
                            }
                        }



                    }else{

                        List<JyMenu> children = menus.getChildren();
                        if (menu.getParentId().intValue() == menus.getId().intValue()){
                            if (children == null) {
                                children = new ArrayList<>();
                                menus.setChildren(children);
                            }
                            operatorChildren(type,children,menu);
                            break;
                        }else {
                            //看所有子集是否存在匹配得上的
                            boolean flag = updateSecurityConstantsMenusChildren(type,children,menu);
                            if (flag){
                                break;
                            }
                        }
                    }

                }*/
            }
        }
    }


    private boolean updateSecurityConstantsMenusChildren(int type,List<JyMenu> menus,JyMenu srcMenu){

        boolean flag = false;

        if(menus != null && menus.size()>0){
            for (JyMenu menu : menus) {
                List<JyMenu> children = menu.getChildren();

                if (srcMenu.getParentId().intValue() == menu.getId().intValue()){
                    if (children == null) {
                        children = new ArrayList<>();

                        menu.setChildren(children);
                    }
                    operatorChildren(type,children,srcMenu);
                    flag = true;
                    break;

                }else {
                    if (children != null) {
                        updateSecurityConstantsMenusChildren(type,children,srcMenu);
                    }
                }
            }
        }

        return flag;
    }
    private void operatorChildren(int type,List<JyMenu> children,JyMenu menu){
        if (type == 1){
            children.add(menu);
        }else if(type == 2){
//            for (JyMenu child : children) {
            for(int i=0;i<children.size();i++){

                if (children.get(i).getId().intValue() == menu.getId().intValue()){
                    children.set(i,menu);
//                    children.add(menu);
//                    child = menu;
                    break;
                }
            }
        }else if(type == 3){
            for (JyMenu child : children) {
                if (child.getId().intValue() == menu.getId().intValue()){
                    children.remove(child);
                    break;
                }
            }

        }
    }

    private boolean validateMenu(JyMenu menu) throws AdscmSystemException{

        menu.setKeepAlive(1);
        menu.setRequireAuth("1");
        menu.setEnabled(1);

        if (menu.getSrcType() == null){
            throw new AdscmSystemException("参数异常：请选择资源类型！");
        }
        if (menu.getParentId() == null){
            throw new AdscmSystemException("参数异常：请选择父级菜单！");
        }
        JyMenu parentMenu = jyMenuMapper.selectById(menu.getParentId());

        if (parentMenu != null && parentMenu.getSrcType().intValue() == 2){
            throw new AdscmSystemException("资源下面不能添加子集菜单或资源！");
        }
        //看当前菜单下面有无其他类型的子菜单
        boolean flag = true;
        Wrapper<JyMenu> wrapper = new EntityWrapper<>();
        wrapper.eq("parentId",menu.getParentId());
        List<JyMenu> menus = jyMenuMapper.selectList(wrapper);
        if (menus != null && menus.size()>0){
            for (JyMenu jyMenu : menus) {
                int srcType = jyMenu.getSrcType();
                if (srcType != menu.getSrcType().intValue()){
                    flag = false;
                    break;
                }
            }
        }

        return flag;
    }

    @Transactional
    @Override
    public void editMenu(JyMenu menu) throws AdscmSystemException {
        if (AdscmBaseUtils.getInstance().isNotEmpty(menu,"name")){
            logger.info("修改菜单【"+menu.getName()+"】...");

            /*menu.setKeepAlive(1);
            menu.setRequireAuth("1");
            menu.setEnabled(1);

            if (menu.getSrcType() == null){
                throw new AdscmSystemException("参数异常：请选择资源类型！");
            }
            if (menu.getParentId() == null){
                throw new AdscmSystemException("参数异常：请选择父级菜单！");
            }
            JyMenu parentMenu = jyMenuMapper.selectById(menu.getParentId());

            if (parentMenu != null && parentMenu.getSrcType().intValue() == 2){
                throw new AdscmSystemException("资源下面不能添加子集菜单或资源！");
            }
            //看当前菜单下面有无其他类型的子菜单
            boolean flag = true;
            Wrapper<JyMenu> wrapper = new EntityWrapper<>();
            wrapper.eq("parentId",menu.getParentId());
            List<JyMenu> menus = jyMenuMapper.selectList(wrapper);
            if (menus != null && menus.size()>0){
                for (JyMenu jyMenu : menus) {
                    int srcType = jyMenu.getSrcType();
                    if (srcType != menu.getSrcType().intValue()){
                        flag = false;
                        break;
                    }
                }
            }*/
            boolean flag = validateMenu(menu);

            if (flag){
                jyMenuMapper.updateById(menu);
            }else{
                throw new AdscmSystemException("当前菜单所属的父级菜单下面只能存在一种资源类型！");
            }

            //修改内存中的menu
            this.updateSecurityConstantsMenus(2,menu);
        }else {
            throw new AdscmSystemException("菜单参数异常【"+menu+"】");
        }
    }

    @Override
    public List<JyMenu> getMenuByParentId(int parentMenuId) throws AdscmSystemException {


        if (AdscmBaseUtils.getInstance().isNotEmpty(parentMenuId,null)){
            logger.info("根据父菜单ID，获取子菜单...");

            JyMenu parentMenu = jyMenuMapper.selectById(parentMenuId);//获取这个菜单本身

            if (AdscmBaseUtils.getInstance().isNotEmpty(parentMenu,null)){

                Map<String,Object> columnMap = new HashMap<>();
                columnMap.put("parentId",parentMenuId);

//                List<JyMenu> allChildren = jyMenuMapper.selectByMap(columnMap);
                List<JyMenu> allMenus = jyMenuMapper.selectList(null);//所有菜单

                if (allMenus != null && allMenus.size()>0){
                    this.recursionJyMenu(parentMenu,allMenus);
                }else {
                    logger.info("菜单【"+parentMenuId+"】没有子菜单...");
                }
                return parentMenu.getChildren();
            }else {
                throw new AdscmSystemException("没有查询到主键为【"+parentMenuId+"】的菜单...");
            }

        }else {
            throw new AdscmSystemException("菜单参数异常【"+parentMenuId+"】");
        }
    }

    @Override
    public JyMenu getAllMenuList() throws AdscmSystemException {

        logger.info("获取所有菜单...");

        EntityWrapper<JyMenu> wapper = new EntityWrapper();
        wapper.eq("parentId",0);

        List<JyMenu> topMenus = jyMenuMapper.selectList(wapper);
        if (topMenus != null && topMenus.size()>0){

            wapper = new EntityWrapper();
            wapper.where("parentId != 0");

            List<JyMenu> otherMenus = jyMenuMapper.selectList(wapper);

            for (JyMenu topMenu : topMenus) {
                this.recursionJyMenu(topMenu,otherMenus);
            }

        }
        JyMenu topMenu = new JyMenu();
        topMenu.setChildren(topMenus);
        return topMenu;
    }

    @Override
    public List<JyMenu> getMenuByName(String menuName) throws AdscmSystemException {

        logger.info("根据菜单名称【"+menuName+"】模糊查询这个菜单以及他的子菜单...");

        EntityWrapper<JyMenu> wapper = new EntityWrapper();
        wapper.where("name like '%"+menuName+"%'");
        List<JyMenu> menus = jyMenuMapper.selectList(wapper);
        List<JyMenu> allMenus = jyMenuMapper.selectList(null);
        if (menus != null && menus.size()>0){
            for (JyMenu menu :
                    menus) {

                this.recursionJyMenu(menu,allMenus);

            }
        }

        return menus;
    }

    @Override
    public List<JyMenu> getMenuAllSrc(int menuId, String tokenId) throws AdscmSystemException {

        logger.info("根据菜单ID【"+menuId+"】和指定用户，获取这个用户能对这个菜单的操作URL集合...");

        if(AdscmBaseUtils.getInstance().isNotEmpty(tokenId,null) ){

            Token token = AdscmBaseUtils.getInstance().getTokenByTokenId(tokenId, tokenRedisTemplate);
            if (AdscmBaseUtils.getInstance().isNotEmpty(token,"user")) {
                JyUser user = token.getUser();

                Map<Integer, JyMenu> menuMap = user.getMenus();


                Wrapper<JyMenu> wrapper = new EntityWrapper<>();
                wrapper.eq("parentId",menuId);
                wrapper.eq("srcType",2);

                List<JyMenu> allMenus = jyMenuMapper.selectList(wrapper);

                if(allMenus != null && allMenus.size()>0){
                    for (JyMenu allMenu : allMenus) {
                        JyMenu temp = menuMap.get(allMenu.getId());
                        if(temp != null){
                            allMenu.setMenuShow(true);
                        }
                    }
                }
                return allMenus;

            }else {
                throw new AdscmSystemException("没有获取到 tokenId 对应的已登录用户...");
            }
        }else {
            throw new AdscmSystemException("传参异常：tokenId IS NULL...");
        }
    }


    @Override
    public List<JyMenu> getRolesSrc(int roleId) {

        logger.info("查询角色能访问的所有菜单开始....");
        long startTime = System.currentTimeMillis();
        List<Integer> lastMenuIds = new ArrayList<>();
        List<Integer> menuIds = jyMenuMapper.selectRolesMenuIds(roleId);


        if (menuIds != null && menuIds.size()>0){
            for (Integer menuId : menuIds) {
                int count = jyMenuMapper.selectByParentCount(menuId);
                if (count <= 0){
                    lastMenuIds.add(menuId);
                }
            }
//        jyMenuMapper.selectMenusByRole(roleId);

            List<JyMenu> menus = null;
            if (lastMenuIds.size() > 0){
                menus = jyMenuMapper.selectBatchIds(lastMenuIds);
            }

            long endTime = System.currentTimeMillis();

            logger.info("查询耗时："+ (endTime - startTime) + " 毫秒！");

            return menus;
        }else {
            logger.info("当前角色没有关联任何菜单....");
            return null;
        }


    }

    /**
     * 递归获取所有子菜单进行构造
     * @param topLevelMenu ：顶级菜单
     * @param menus：所有菜单
     * @return
     */
    private void recursionJyMenu(JyMenu topLevelMenu,List<JyMenu> menus){

        Integer srcType = topLevelMenu.getSrcType();
        if (srcType == 1){
            topLevelMenu.setEdit(true);
        }else {
            topLevelMenu.setEdit(false);
        }

        List<JyMenu> childrenMenus = new ArrayList<>();
        for (JyMenu menu : menus) {
            if (menu.getParentId() != null && menu.getParentId().intValue() == topLevelMenu.getId().intValue()){
                childrenMenus.add(menu);
            }
            srcType = menu.getSrcType();
            if (srcType == 1){
                menu.setEdit(true);
            }else {
                menu.setEdit(false);
            }
        }

        if (childrenMenus.size()>0){
            topLevelMenu.setLeaf(false);
            for (JyMenu menu :
                    childrenMenus) {
                recursionJyMenu(menu,menus);
            }
        }
        topLevelMenu.setChildren(childrenMenus);
    }

    @Override
    public void ttt(int menuId) {
//        Wrapper<JyMenu> wrapper = new EntityWrapper<>();
//        wrapper.where("id > 135 AND id < 272");
//        List<JyMenu> allMenus = jyMenuMapper.selectList(wrapper);
//
//        int i = 137;
//        for (JyMenu menu : allMenus) {
//            String path = menu.getPath();
//            path = path.substring(0,path.lastIndexOf("/")+1);
//
//            menu.setPath(path + menu.getId());
//            jyMenuMapper.updateById(menu);
//        }

        JyMenu menu = jyMenuMapper.selectById(menuId);

        aaa(menu);




    }

    private void aaa(JyMenu menu){
        Wrapper<JyMenu> wrapper = new EntityWrapper<>();
        wrapper.eq("parentId",menu.getId());
        wrapper.eq("srcType",1);
        List<JyMenu> allMenus = jyMenuMapper.selectList(wrapper);

        if (allMenus != null && allMenus.size()>0){
            //再获取子集
            for (JyMenu am : allMenus) {
                aaa(am);
            }
        }else {
            //最底层了，进行添加
//            String path = menu.getPath();
//            path = path.substring(path.lastIndexOf("/")+1);

            JyMenu m1 = new JyMenu();
            m1.setName(menu.getName() + "-新增基本信息");
//            m1.setUrl("/adscm/zltx/print/"+path);
//            m1.setPath(m1.getUrl());
            m1.setParentId(menu.getId());
            m1.setSrcType(2);
            m1.setComponent("addBaseInfo");
            jyMenuMapper.insert(m1);

            JyMenu m2 = new JyMenu();
            m2.setName(menu.getName() + "-文件发布");
//            m1.setUrl("/adscm/zltx/print/"+path);
//            m1.setPath(m1.getUrl());
            m2.setParentId(menu.getId());
            m2.setSrcType(2);
            m2.setComponent("fileRelease");
            jyMenuMapper.insert(m2);

            JyMenu m3 = new JyMenu();
            m3.setName(menu.getName() + "-新增申请记录/编辑");
//            m1.setUrl("/adscm/zltx/print/"+path);
//            m1.setPath(m1.getUrl());
            m3.setParentId(menu.getId());
            m3.setSrcType(2);
            m3.setComponent("addEditApplyInfo");
            jyMenuMapper.insert(m3);

            JyMenu m4 = new JyMenu();
            m4.setName(menu.getName() + "-新增发放记录/打印");
//            m1.setUrl("/adscm/zltx/print/"+path);
//            m1.setPath(m1.getUrl());
            m4.setParentId(menu.getId());
            m4.setSrcType(2);
            m4.setComponent("addPrintGrantInfo");
            jyMenuMapper.insert(m4);

            JyMenu m5 = new JyMenu();
            m5.setName(menu.getName() + "-审核");
//            m1.setUrl("/adscm/zltx/print/"+path);
//            m1.setPath(m1.getUrl());
            m5.setParentId(menu.getId());
            m5.setSrcType(2);
            m5.setComponent("auditingApply");
            jyMenuMapper.insert(m5);

//            JyMenu m2 = new JyMenu();
//            m2.setName("根据id修改现场指导原则数据");
//            m2.setUrl("/adscm/zltx/maai_production/updateContent/"+path);
//            m2.setPath(m2.getUrl());
//            m2.setParentId(menu.getId());
//            m2.setSrcType(2);
//            jyMenuMapper.insert(m2);
//
//            JyMenu m3 = new JyMenu();
//            m3.setName("根据id删除现场指导原则数据");
//            m3.setUrl("/adscm/zltx/maai_production/deleteContent/"+path);
//            m3.setPath(m3.getUrl());
//            m3.setParentId(menu.getId());
//            m3.setSrcType(2);
//            jyMenuMapper.insert(m3);
//
//            JyMenu m4 = new JyMenu();
//            m4.setName("根据菜单id查询现场指导原则");
//            m4.setUrl("/adscm/zltx/maai_production/queryProduction/"+path);
//            m4.setPath(m4.getUrl());
//            m4.setParentId(menu.getId());
//            m4.setSrcType(2);
//            jyMenuMapper.insert(m4);
//
//            JyMenu m5 = new JyMenu();
//            m5.setName("模糊查询内容");
//            m5.setUrl("/adscm/zltx/maai_production/searchAllCondition/"+path);
//            m5.setPath(m5.getUrl());
//            m5.setParentId(menu.getId());
//            m5.setSrcType(2);
//            jyMenuMapper.insert(m5);

        }



    }



    //
//    public static void main(String[] args) {
//
//
//        List<JyMenu> menuList = new ArrayList<>();
//
//        JyMenu m1 = new JyMenu();
//        JyMenu m2 = new JyMenu();
//        JyMenu m3 = new JyMenu();
//        JyMenu m4 = new JyMenu();
//        JyMenu m5 = new JyMenu();
//        JyMenu m6 = new JyMenu();
//        JyMenu m7 = new JyMenu();
//        JyMenu m8 = new JyMenu();
//
//        m1.setId(2);
//        m1.setParentId(1);
//
//        m2.setId(3);
//        m2.setParentId(1);
//
//        m3.setId(4);
//        m3.setParentId(2);
//
//        m4.setId(5);
//        m4.setParentId(2);
//
//        m5.setId(6);
//        m5.setParentId(2);
//
//        m6.setId(7);
//        m6.setParentId(4);
//
//        m7.setId(8);
//        m7.setParentId(7);
//
//        m8.setId(9);
//        m8.setParentId(8);
//
//
//
//        menuList.add(m1);
//        menuList.add(m2);
//        menuList.add(m3);
//        menuList.add(m4);
//        menuList.add(m5);
//        menuList.add(m6);
//        menuList.add(m7);
//        menuList.add(m8);
//
//
//        JyMenuServiceImpl j = new JyMenuServiceImpl();
//        j.recursionJyMenu(m1,menuList);
//
//        System.out.println(m1);
//
//    }

}
